package com.example.serverdemo.netty.device_tcp_server.function_module;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.serverdemo.bean.LightControllerBean;
import com.example.serverdemo.bean.json.device.LightControllerParameterBean;
import com.example.serverdemo.netty.device_tcp_server.handler.DeviceHandler;
import com.example.serverdemo.netty.device_tcp_server.type.FunctionType;
import com.example.serverdemo.utils.log.PrintLogUtil;
import com.example.serverdemo.utils.stringutils.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class LightingControllerFunctionModule extends BaseFunctionModule{
    private static final int  PACKET_SIZE=1024 * 2;
    private FunctionType functionType;
    private int processControlIdentification;
    private LightControllerParameterBean currentBean;

    public LightingControllerFunctionModule(DeviceHandler handler) {
        this.init();
        this.bindDeviceHandler(handler);
    }
    @Override
    protected void init() {
        super.init();
        this.processControlIdentification = 0;
    }
    @Override
    protected boolean success(Object obj) {
        try {
            switch (this.functionType){
                case LightingControllerParameterReadBack:
                    this.readBackLightControllerParameterSuccess(obj);
                    break;
                case LightingControllerParameterConfiguration:
                    this.configurationLightControllerParameterSuccess(obj);
                    break;
            }
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    @Override
    protected boolean failed(String msg) {
        try {
            switch (this.functionType){
                case LightingControllerParameterReadBack:
                    this.readBackLightControllerParameterFailed("Lighting Controller Parameter Read Back Failed :" + msg);
                    break;
                case LightingControllerParameterConfiguration:
                    this.configurationLightControllerParameterFailed("Lighting Controller Parameter Configuration Failed :" + msg);
                    break;
            }
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    private void initParams(){
        this.functionType = FunctionType.Null;
        this.handler.currentFunctionType = FunctionType.Null;
        this.processControlIdentification = 0;
        this.currentBean = null;
        this.handler.setFunctionKey(true);
    }
    @Override
    public boolean msgDistributionTransactionManagement(byte[] msg) {
        switch (this.functionType) {
            case LightingControllerParameterReadBack:
                return this.readBackLightControllerParameterMsgManagement(msg);
            case LightingControllerParameterConfiguration:
                return this.configurationLightControllerParameterMsgManagement(msg);
        }
        return false;
    }
    //Read
    public boolean readBackLightControllerParameter(){
        try {
            if (!this.handler.isFunctionKey()) return false;
            if (this.handler.deviceId == null) return false;
            this.handler.setFunctionKey(false);
            this.functionType = FunctionType.LightingControllerParameterReadBack;
            this.processControlIdentification = 0;
            this.readBackLightControllerParameterTask();
            return true;
        }catch (Exception e){
            this.failed("Read Back Light Controller Parameter Failed By Task Start");
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    private boolean readBackLightControllerParameterTask(){
        try {
            List<String> params = new ArrayList<>();
            switch (this.processControlIdentification){
                case 0:
                    params.clear();
                    params.add("zg");
                    params.add("2");
                    this.sendOrder("Relay",params, Convert.intToByte(0x05),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 1:
                    this.sendData("zg".getBytes(),Convert.intToByte(0x02),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 3:
                    params.clear();
                    params = new ArrayList<>();
                    params.add("rg");
                    params.add("2");
                    this.sendOrder("Relay",params, Convert.intToByte(0x05),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 4:
                    this.sendData("rg".getBytes(),Convert.intToByte(0x02),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
            }
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    private boolean readBackLightControllerParameterMsgManagement(byte[] msg){
        try {
            byte[] data = ArrayUtil.sub(msg,8,msg.length);
            String msgStr = new String(data);
            this.stopOverTimeDetectionTask();
            if (this.processControlIdentification < 5){
                switch (msgStr){
                    case "Ok:Decode":
                    case "Done":
                    case "ack\r\n":
                        this.processControlIdentification++;
                        this.readBackLightControllerParameterTask();
                        break;
                    default:this.readBackLightControllerParameterFailed("Receive Error Msg：" + msgStr);
                }
            }else {
                LightControllerParameterBean bean = LightControllerParameterBean.build(data);
                if (bean == null) return false;
                this.readBackLightControllerParameterSuccess(bean);
            }
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    private void readBackLightControllerParameterSuccess(Object obj){
        LightControllerBean bean = new LightControllerBean();
        LightControllerParameterBean data = (LightControllerParameterBean) obj;
        bean.setDeviceId(this.handler.deviceId);
        bean.setJsonStr(JSON.toJSONString(data));
        if (this.handler.lightControllerService.queryLightControllerParameter(this.handler.deviceId) == null){
            this.handler.lightControllerService.addLightControllerParameter(bean);
            PrintLogUtil.printInfo(this,"Add Light Controller Parameter Success");
        }else {
            this.handler.lightControllerService.updateLightControllerParameter(bean);
            PrintLogUtil.printInfo(this,"Update Light Controller Parameter Success");
        }
        this.initParams();
    }
    private void readBackLightControllerParameterFailed(String msg){
        PrintLogUtil.printInfo(this,"Read Back Light Controller Parameter Failed :" + msg);
        this.initParams();
    }
    //configuration
    public boolean configurationLightControllerParameter(LightControllerParameterBean bean){
        try {
            if (!this.handler.isFunctionKey()) return false;
            if (this.handler.deviceId == null) return false;
            this.handler.setFunctionKey(false);
            this.functionType = FunctionType.LightingControllerParameterConfiguration;
            this.currentBean = bean;
            this.processControlIdentification = 0;
            this.configurationLightControllerParameterTask();
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
       return false;
    }
    private boolean configurationLightControllerParameterTask(){
        try {
            if (this.currentBean == null) return false;
            List<String> params = new ArrayList<>();
            byte[] data;
            switch (this.processControlIdentification){
                case 0:
                    params.clear();
                    params.add("zg");
                    params.add("2");
                    this.sendOrder("Relay",params, Convert.intToByte(0x05),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 1:
                    this.sendData("zg".getBytes(),Convert.intToByte(0x02),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 3:
                    params.clear();
                    params.add("dg");
                    params.add("" +"dg".getBytes("GBK").length);
                    this.sendOrder("Relay",params,Convert.intToByte(0x05),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 4:
                    data = "dg".getBytes("GBK");
                    this.sendData(data,Convert.intToByte(0x02),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 6:
                    data = this.currentBean.toHexData();
                    params.clear();
                    params.add("dg");
                    params.add("" + data.length);
                    this.sendOrder("Relay",params,Convert.intToByte(0x05),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 7:
                    data = this.currentBean.toHexData();
                    System.out.println(StringUtils.printHexString(data));
                    this.sendData(data,Convert.intToByte(0x02),Convert.intToByte(this.handler.currentDeviceInfo.getDeviceAddress()),true);
                    break;
                case 9:
                    this.success(null);
            }
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    private boolean configurationLightControllerParameterMsgManagement(byte[] msg){
        try {
            byte[] data = ArrayUtil.sub(msg,8,msg.length);
            String msgStr = new String(data);
            this.stopOverTimeDetectionTask();
            switch (msgStr){
                case "Ok:Decode":
                case "Done":
                case "ack\r\n":
                    this.processControlIdentification++;
                    if (!this.configurationLightControllerParameterTask()){
                        this.failed("Configuration Light Controller Parameter Failed By Send Error , Current Progress is " + this.processControlIdentification);
                    }
                    break;
                default:
                    this.failed("Receive Error Msg : " + msgStr);
                    break;
            }
            return true;
        }catch (Exception e){
            PrintLogUtil.printError(this,e);
        }
        return false;
    }
    private void configurationLightControllerParameterSuccess(Object obj){
        PrintLogUtil.printInfo(this,"Configuration Light Controller Parameter Success");
        this.initParams();
        this.handler.closeHandler();
    }
    private void configurationLightControllerParameterFailed(String msg){
        PrintLogUtil.printInfo(this,"Configuration Light Controller Parameter Failed : " + msg);
        this.initParams();
    }
}
